package mh;

import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.logging.Logger;

import javax.swing.JOptionPane;

import mh.chat.MessageType;
import mh.message.IncomingMessage;
import mh.util.SHAHash;

import org.lwjgl.Sys;

public class MessageExecutor implements Runnable {
	/**
	 * The Logger
	 */
	private static final Logger	LOG			= Logger.getLogger(MessageExecutor.class.getName());

	private MagicHogwarts		mh;
	private ClientTCP			cl;
	private boolean				running		= false;
	private boolean				loggedIn	= false;
	private IncomingMessage		receivedMsg;

	public MessageExecutor(MagicHogwarts mh, ClientTCP cl) {
		this.mh = mh;
		this.cl = cl;
	}

	/**
	 * The procedure to autenticate to the server.
	 * 
	 * @param nickname
	 *            The nickname to be sent to the server.
	 * @param password
	 *            The password will be sent (hashed) to the server.
	 */
	public void login(String nickname, char[] password) {
		if (this.cl == null) {
			throw new RuntimeException();
		}
		long s = Sys.getTime();
		this.cl.send("NICK " + nickname);
		IncomingMessage reply = null;
		try {
			reply = this.mh.getMessage(); //The response to NICK msg
			if (reply.getCommand().equalsIgnoreCase("LOGIN")) {
				ArrayList<String> params = reply.getParams();
				String accountSalt = params.get(0);
				String randomSalt = params.get(1);
				try {
					String sharedSecret = SHAHash.digestSalted(accountSalt, password);
					String saltedSharedSecret = SHAHash.digestSalted(randomSalt, sharedSecret);
					if (saltedSharedSecret != null) {
						this.cl.send("PASS " + saltedSharedSecret);
						reply = this.mh.getMessage();
						if (reply.getCommand().equalsIgnoreCase("WELCOME") && reply.getParams().get(0).equals(nickname)) {
							// ************ LOG ************ //
							LOG.config("Logged in.");
							// ***************************** //
							this.running = true;
							this.loggedIn = true;
							this.mh.startExecutor();
							LOG.config("Time passed: " + (Sys.getTime() - s));
							this.mh.startGame();
						} else {
							// ************ LOG ************ //
							LOG.warning("A problem has occured while trying to login to the server.");
							// ***************************** //
							JOptionPane.showMessageDialog(null, "Error while logging to the server, shutting down.\n- ERROR 006 -");
							System.exit(0);
						}
					}
				} catch (NoSuchAlgorithmException e) {
					// ************ LOG ************ //
					LOG.warning("Error while SHA hashing the password, shutting down.");
					// ***************************** //
					JOptionPane.showMessageDialog(null, "Error while SHA hashing the password, shutting down.\n- ERROR 005 -");
					System.exit(0);
				}
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void run() {

		this.running = true;
		while (this.running && this.loggedIn) {
			try {
				this.receivedMsg = this.mh.getMessage();

				if (this.receivedMsg != null) {
					// ****** DEBUG ****** //
					LOG.fine("Analyzing message " + this.receivedMsg.getCommand());
					// ******************* //

					this.commandInterpreter(this.receivedMsg);

				}
			} catch (InterruptedException e) {
				// ************ LOG ************ //
				LOG.warning("Error in retreive the message from the queue. Stopping executor.");
				// ***************************** //
				JOptionPane.showMessageDialog(null, "Error in retreive the message from the queue, shutting down.\n- ERROR 007 -");
				this.running = false;
				System.exit(0);
			}
		}
	}

	private void commandInterpreter(IncomingMessage incomingMsg) {
		MessageType mt = MessageType.valueOf(incomingMsg.getCommand());
		switch (mt) {
			case MOVE: {
				//TODO check if the player can move and answer
				break;
			}
			case CHAT: {
				//TODO send a private message to another player
				break;
			}
			case BROADCAST: {
				//TODO send a message to all the people in the map
				break;
			}

			case PING: {
				this.cl.send("PONG");
				break;
			}
			default: {
				//XXX if you are here you have done something nasty!
			}
		}
	}

}
